﻿using System;
using System.Collections.Generic;
using System.Text;

namespace ArgusPCLib.Threading.Collections
{
	public class SynchronizedDictionaryWrapper<TKey,TValue> : SynchronizedDictionaryBase<TKey,TValue>
	{
		IDictionary<TKey, TValue> dictionary;
		KeyCollection keys;
		ValueCollection values;

		public SynchronizedDictionaryWrapper(IDictionary<TKey, TValue> dictionary)
			: this(dictionary, new object()) { }

		public SynchronizedDictionaryWrapper(IDictionary<TKey, TValue> dictionary, object syncRoot)
			: base(syncRoot)
		{
			this.dictionary = dictionary;
			this.keys = new KeyCollection(this.dictionary.Keys, syncRoot);
			this.values = new ValueCollection(this.dictionary.Values, syncRoot);
		}

		protected override ISynchronizedEnumerator<KeyValuePair<TKey, TValue>> GetEnumeratorCore()
		{
			return new SynchronizedEnumeratorWrapper<KeyValuePair<TKey, TValue>>(this.dictionary.GetEnumerator(), this.SyncRoot);
		}

		protected override int CountGetCore() { return this.dictionary.Count; }
		protected override bool IsReadOnlyGetCore() { return this.dictionary.IsReadOnly; }
		protected override void AddCore(KeyValuePair<TKey, TValue> item) { this.dictionary.Add(item); }
		protected override void AddCore(TKey key, TValue value) { this.dictionary.Add(key, value); }
		protected override void ClearCore() { this.dictionary.Clear(); }
		protected override bool ContainsCore(KeyValuePair<TKey, TValue> item) { return this.dictionary.Contains(item); }
		protected override bool ContainsKeyCore(TKey key) { return this.dictionary.ContainsKey(key); }
		protected override void CopyToCore(KeyValuePair<TKey, TValue>[] array, int index) { this.dictionary.CopyTo(array, index); }
		protected override TValue ItemGetCore(TKey key) { return this.dictionary[key]; }
		protected override void ItemSetCore(TKey key, TValue value) { this.dictionary[key] = value; }
		protected override bool RemoveCore(KeyValuePair<TKey, TValue> item) { return this.dictionary.Remove(item); }
		protected override bool RemoveCore(TKey key) { return this.dictionary.Remove(key); }
		protected override bool TryGetValueCore(TKey key, out TValue value) { return this.dictionary.TryGetValue(key, out value); }

		protected override ISynchronizedCollection<TKey> KeysGetCore()
		{
			return this.keys;
		}

		protected override ISynchronizedCollection<TValue> ValuesGetCore()
		{
			return this.values;
		}

		public int Count { get { return ((ICollection<KeyValuePair<TKey, TValue>>)this).Count; } }
		public bool IsReadOnly { get { return ((ICollection<KeyValuePair<TKey, TValue>>)this).IsReadOnly; } }
		public ISynchronizedCollection<TKey> Keys { get { return ((ISynchronizedDictionary<TKey, TValue>)this).Keys; } }
		public ISynchronizedCollection<TValue> Values { get { return ((ISynchronizedDictionary<TKey, TValue>)this).Values; } }

		public void Add(KeyValuePair<TKey, TValue> item) { ((ICollection<KeyValuePair<TKey, TValue>>)this).Add(item); }
		public void Clear() { ((ICollection<KeyValuePair<TKey, TValue>>)this).Clear(); }
		public bool Contains(KeyValuePair<TKey, TValue> item) { return ((ICollection<KeyValuePair<TKey, TValue>>)this).Contains(item); }
		public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index) { ((ICollection<KeyValuePair<TKey, TValue>>)this).CopyTo(array, index); }
		public bool Remove(KeyValuePair<TKey, TValue> item) { return ((ICollection<KeyValuePair<TKey, TValue>>)this).Remove(item); }
		public bool Remove(TKey key) { return ((IDictionary<TKey, TValue>)this).Remove(key); }

		public abstract class ReadOnlyCollection<T> : SynchronizedCollectionBase<T>
		{
			ICollection<T> collection;

			public ReadOnlyCollection(ICollection<T> collection, object syncRoot)
				: base(syncRoot)
			{
				this.collection = collection;
			}

			protected override int CountGetCore() { return this.collection.Count; }
			protected override bool IsReadOnlyGetCore() { return true; }
			protected override void AddCore(T item) { throw new NotSupportedException(); }
			protected override void ClearCore() { throw new NotSupportedException(); }
			protected override bool RemoveCore(T item) { throw new NotSupportedException(); }
			protected override bool ContainsCore(T item) { return this.collection.Contains(item); }
			protected override void CopyToCore(T[] array, int index) { this.collection.CopyTo(array, index); }

			protected override ISynchronizedEnumerator<T> GetEnumeratorCore()
			{
				return new SynchronizedEnumeratorWrapper<T>(this.collection.GetEnumerator(), this.SyncRoot);
			}

			public int Count { get { return ((ICollection<T>)this).Count; } }
			public bool IsReadOnly { get { return ((ICollection<T>)this).IsReadOnly; } }
			public bool Contains(T item) { return ((ICollection<T>)this).Contains(item); }
			public void CopyTo(T[] array, int index) { ((ICollection<T>)this).CopyTo(array, index); }
		}

		public class KeyCollection : ReadOnlyCollection<TKey>
		{
			internal KeyCollection(ICollection<TKey> keys, object syncRoot)
				: base(keys, syncRoot) { }
		}

		public class ValueCollection : ReadOnlyCollection<TValue>
		{
			internal ValueCollection(ICollection<TValue> values, object syncRoot)
				: base(values, syncRoot) { }
		}
	}
}
